/**
*  \file tasklet.c
*
*  \brief Administration of light-weight tasks.
*
*  \author Michael J. Hohmann <michael.hohmann@linde-mh.de>
*
*  The module tasklet provide the ability to organize callback like functions
*  in a double linked lists.
*
*/

/*===============================================[ private includes  ]================================================*/
#include <stddef.h>
#include "tasklet.h"

/*===============================================[ private defines   ]================================================*/

/*===============================================[ private datatypes ]================================================*/

/*===============================================[ private variables ]================================================*/

/*===============================================[ public variables  ]================================================*/

/*===============================================[ private functions ]================================================*/
static U32 tasklet_default_timefunction( void );

/*====================================================================================================================*/

struct tasklet_list * tasklet_list_initialize( struct tasklet_list *list, tasklet_timer_function_t timer_function )
{
   if( NULL != list )
   {
      LIST_INIT( &list->tasklet_list );

      if( NULL == timer_function )
      {
         list->timer_function = tasklet_default_timefunction;
      }
      else
      {
         list->timer_function = timer_function;
      }

      list->process_time = 0 ;
      list->observer=0;
   }
   return list;
}

struct tasklet* tasklet_assign( struct tasklet_list *list, struct tasklet *task, tasklet_function_t func, void* data )
{
   if( ( NULL != list ) && ( NULL != task ) && ( NULL != func ) )
   {
      struct tasklet_data *p=LIST_DATA(task);
      p->data=data;
      p->function=func;
      LIST_PUSH_BACK( &list->tasklet_list, task);
      return task;
   }

   return NULL;
}

U16 tasklet_perform( struct tasklet_list *list  )
{
   U16 count = 0; /* will count number of processed tasklets */

   if(  NULL != list )
   {
      U32 time = list->timer_function();

      struct tasklet* p=LIST_FIRST( &list->tasklet_list);

      while( NULL != p)
      {
         struct tasklet* next=LIST_NEXT( p );
         /* remember next element. This is imporatant if item will be unlinked in the next function call. */

         U32 tasklet_time = list->timer_function();

         LIST_DATA(p)->function(p);

         tasklet_time = list->timer_function() - tasklet_time;

         if( tasklet_time > LIST_DATA(p)->tasklet_time )
         {
            LIST_DATA(p)->tasklet_time = tasklet_time;
         }
         count++;
         p=next;
      }

      /* Calculate process time and store maximum */
      time = list->timer_function() - time;

      if ( time >  list->process_time )
      {
         list->process_time = time;
      }

      list->observer=0; /* clear observer in order to indicate the slice has completed */
   }

   return count;
}

/** Default time function
*
*  This function will be called if no time function is passed to the initialize function.
*
*  \return always 0.
**/
static U32 tasklet_default_timefunction( void )
{
   return 0;
}

/***********************************************************************************************************************
*                             Copyright 2007,2011 Linde Material Handling. All rights reserved.                        *
***********************************************************************************************************************/
